#include "win.h"
#if defined win_device_support

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

namespace sleek
{
    namespace core
    {
        namespace device
        {
            Device_win::Device_win(Device_stub a) : Device(a)
            {
                gl[0] = gl[1] = gl[2] = gl[3] = 0;
                running = true;
                    wc.style = CS_OWNDC;
                    wc.lpfnWndProc = WndProc;
                    wc.cbClsExtra = 0;
                    wc.cbWndExtra = 0;
                    wc.hInstance = 0;
                    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
                    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
                    wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
                    wc.lpszMenuName = NULL;
                    wc.lpszClassName = "Sleekthink";
                RegisterClass( &wc );

                screen = CreateWindow( "Sleekthink", a.name.c_str(), WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 0, 0, a.size.width, a.size.height, NULL, NULL, 0, NULL );
                dc = GetDC(screen);
                    ZeroMemory( &pfd, sizeof( pfd ) );
                    pfd.nSize = sizeof( pfd );
                    pfd.nVersion = 1;
                    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
                    pfd.iPixelType = PFD_TYPE_RGBA;
                    pfd.cColorBits = a.bits;
                    pfd.cDepthBits = 16;
                    pfd.iLayerType = PFD_MAIN_PLANE;
                    int format = ChoosePixelFormat(dc, &pfd);
                    SetPixelFormat(dc, format, &pfd);
                makeRenderContext(GRC_0);
                switchToRenderContext(GRC_0);
                setVideoSize(a.size);
                enableWindowDecorator(info.decorator);

                initOpenCL();
                welcomeMessage();
                testGlError();
                glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
            }
            Device_win::~Device_win()
            {
                wglMakeCurrent(0,0);
                ReleaseDC(screen, dc);
                destroyRenderContext(GRC_0);
                destroyRenderContext(GRC_1);
                destroyRenderContext(GRC_2);
                destroyRenderContext(GRC_3);
                DestroyWindow(screen);
            }
            void Device_win::makeRenderContext(GL_RENDER_CONTEXT i)
            {
                gl[i] = wglCreateContext(dc);
                if(gl[i] && i != GRC_0) wglShareLists(gl[0],gl[i]);
                Device::makeRenderContext(i);
            }
            void Device_win::initOpenCL()
            {
                Device::initOpenCL();
            }
            void Device_win::destroyRenderContext(GL_RENDER_CONTEXT i)
            {
                if(gl[i]) wglDeleteContext(gl[i]);
                Device::destroyRenderContext(i);
                gl[i] = 0;
            }
            void Device_win::switchToRenderContext(GL_RENDER_CONTEXT i)
            {
                wglMakeCurrent(dc,gl[i]);
                Device::switchToRenderContext(i);
            }
            void Device_win::setCaption(os::stringc name)
            {
                SetWindowText(screen, name.c_str());
                Device::setCaption(name);
            }
            void Device_win::setVideoSize(math::vector2di i)
            {
                Device::setVideoSize(i);
                ShowWindow(screen, SW_SHOW);
                UpdateWindow(screen);
                MoveWindow(screen, (GetSystemMetrics(SM_CXSCREEN)-i.width)/2, (GetSystemMetrics(SM_CYSCREEN)-i.height)/2, i.width, i.height, FALSE);
            }
            void Device_win::setWindowPos(math::vector2di i)
            {
                ShowWindow(screen, SW_SHOW);
                UpdateWindow(screen);
                MoveWindow(screen, i.width, i.height, info.size.width, info.size.height, FALSE);
                Device::setVideoSize(i);
            }
            math::vector2di Device_win::getDesktopVideoSize()
            {
                return core::math::vector2di(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
            }
            void Device_win::enableWindowDecorator(bool flag)
            {
                Device::enableWindowDecorator(flag);
                SetWindowLong(screen, GWL_STYLE, flag ? WS_CAPTION | WS_SYSMENU | WS_VISIBLE : WS_DLGFRAME);
                ShowWindow(screen, SW_SHOW);
                UpdateWindow(screen);
                SetWindowPos(screen, 0,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
            }
            void Device_win::setGamma(texture::pixel c)
            {
            }
            void Device_win::setFullScreen(bool f)
            {
            }
            bool Device_win::run()
            {
                MSG msg;
                while(PeekMessage(&msg,screen,0,0,PM_NOREMOVE) && running)
                {
                    if(!GetMessage(&msg,screen,0,0)) running = false;//current->exit_msg = true;
                    DispatchMessage(&msg);
                }
                return Device::run();
            }
            void Device_win::begin(texture::pixel color)
            {
                Device::begin(color);
            }
            void Device_win::exit()
            {
                PostQuitMessage(0);
                Device::exit();
            }
            void Device_win::end()
            {
                Device::end();
                SwapBuffers(dc);
            }
        }
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
        case WM_CREATE: return 0;
        case WM_CLOSE: PostQuitMessage( 0 ); return 0;
        case WM_DESTROY: PostQuitMessage( 0 ); return 0;
        case WM_KEYDOWN: if( wParam == VK_ESCAPE) PostQuitMessage(0); return 0;
        default: return DefWindowProc( hWnd, message, wParam, lParam );
	}
}

#endif
